package cn.iocoder.yudao.module.member.service.order;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.ipa.MbUtil;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.member.controller.admin.order.vo.*;
import cn.iocoder.yudao.module.member.controller.admin.profit.vo.ProfitSaveReqVO;
import cn.iocoder.yudao.module.member.controller.admin.siteconfig.vo.SiteConfigurationVo;
import cn.iocoder.yudao.module.member.controller.admin.siteconfig.vo.UserPoolConfigDetailVo;
import cn.iocoder.yudao.module.member.controller.admin.siteconfig.vo.UserPoolConfigVo;
import cn.iocoder.yudao.module.member.controller.app.order.vo.*;
import cn.iocoder.yudao.module.member.convert.order.MemberCertificateOrderConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.order.MemberCertificateOrderDo;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserExtendDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserPriceDetailDo;
import cn.iocoder.yudao.module.member.dal.mysql.order.MemberCertificateOrderMapper;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserExtendMapper;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
import cn.iocoder.yudao.module.member.dal.redis.no.OrderNoRedisDAO;
import cn.iocoder.yudao.module.member.enums.SysFlagEnum;
import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
import cn.iocoder.yudao.module.member.service.cardsecurity.CardSecurityService;
import cn.iocoder.yudao.module.member.service.device.MemberDeviceRecordService;
import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService;
import cn.iocoder.yudao.module.member.service.profit.ProfitService;
import cn.iocoder.yudao.module.member.service.siteconfiguration.SiteConfigurationService;
import cn.iocoder.yudao.module.member.service.siteconfiguration.UserPoolConfigDetailService;
import cn.iocoder.yudao.module.member.service.siteconfiguration.UserPoolConfigService;
import cn.iocoder.yudao.module.member.service.user.MemberUserExtendService;
import cn.iocoder.yudao.module.member.service.user.MemberUserPriceDetailService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.member.util.RobbleWXUtil;
import cn.iocoder.yudao.module.signature.enums.AppleAccountType;
import cn.iocoder.yudao.module.signature.enums.AppleDeviceType;
import cn.iocoder.yudao.module.signature.enums.ClassType;
import cn.iocoder.yudao.module.signature.model.MobileProvisionCreateModel;
import cn.iocoder.yudao.module.signature.model.MobileProvisionResultModel;
import cn.iocoder.yudao.module.signature.service.device.AppleDeviceService;
import cn.iocoder.yudao.module.signature.validatap12status.dto.CertAndMobileprovisionDTO;
import cn.iocoder.yudao.module.signature.validatap12status.dto.CertStatusDTO;
import cn.iocoder.yudao.module.signature.validatap12status.util.CertUtil;
import cn.iocoder.yudao.module.signature.validatap12status.util.OCSPUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.member.enums.profit.ProfitBizTypeEnum.ADD_CERTIFICATE_ORDER;
import static cn.iocoder.yudao.module.member.enums.profit.ProfitBizTypeEnum.ADD_UP_LOAD;

@Service
@Validated
@Slf4j
public class  CertificateOrderServiceImpl  implements CertificateOrderService{


    @Resource
    private OrderNoRedisDAO orderNoRedisDAO;
    private final String CERTIFICATE_ORDER = "CO";
    //标准版
    private final String STANDARD_EDITION_CODE = "VT3";

    @Resource
    private SiteConfigurationService siteConfigurationService;
    @Resource
    private MemberCertificateOrderMapper memberCertificateOrderMapper;

    @Resource
    private MemberUserService memberUserService;
    @Resource
    private MemberUserExtendService memberUserExtendService;

    @Resource
    private MemberUserMapper memberUserMapper;
    @Resource
    private MemberUserExtendMapper memberUserExtendMapper;
    @Resource
    private MemberUserPriceDetailService memberUserPriceDetailService;
    @Resource
    private UserPoolConfigDetailService userPoolConfigDetailService;
    @Resource
    private MemberPointRecordService pointRecordService;
    @Resource
    private MemberDeviceRecordService memberDeviceService ;
    @Resource
    private AppleDeviceService appleDeviceService ;
    @Resource
    private UserPoolConfigService userPoolConfigService ;
    @Resource
    private ProfitService profitService ;
    @Lazy
    @Resource
    private CardSecurityService cardSecurityService;

    @Resource
    private FileApi fileApi;

    private final String SITE_CONFIG_CACHE_TOKEN = "SITE:CONFIG:CACHE:TOKEN";
    private final String SITE_CONFIG_CACHE_AUTOMATIC_FLAG = "SITE:CONFIG:CACHE:AUTOMATIC:FLAG";
    //B系统调用A系统的接口
    private final String B_To_A = "/app-api/member/certificate/createOrder";

    private final String Login_TO_A = "/app-api/member/auth/loginByToken";

    private final String SITE_CONFIG_CACHE_MAIN_URL = "SITE:CONFIG:CACHE:MAIN:URL";
    private final String SITE_CONFIG_CACHE_MAIN_CODE = "SITE:CONFIG:CACHE:MAIN:CODE";

    @Resource
    private List<SysLinkStrategy>  sysLinkStrategys;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public MemberCertificateOrderDo createOrder(AppMemberCertificateOrderVo appOrderVo) throws Exception {

        //获取用户信息
        Long loginUserId;
        if (ObjectUtil.isEmpty(appOrderVo.getUserId())){
            loginUserId =  getLoginUserId();
        }else {
            loginUserId =  appOrderVo.getUserId();
        }
        String value = orderNoRedisDAO.getValue(appOrderVo.getUdid() + loginUserId+ appOrderVo.getForce());
        if (ObjectUtil.isNotEmpty(value)){
            throw exception(ERROR_MESSAGE_REPEAT);
        }else {
            orderNoRedisDAO.saveMessage(appOrderVo.getUdid() + loginUserId+ appOrderVo.getForce(),appOrderVo.getUdid());
        }
        MemberUserDO user = memberUserService.getUser(loginUserId);
        MemberUserExtendDO userExtendDO = memberUserExtendService.getUserExtend(loginUserId);
        appOrderVo.setCertificateOrderCode(orderNoRedisDAO.generate(CERTIFICATE_ORDER));
        appOrderVo.setUserName(user.getNickname());
        //同一个udid 在一个类型里面只能纯在一个订单
        //根据购买类型 + udid  查询最后一条数据
        MemberCertificateOrderDo memberCertificateOrderDoByDb =  memberCertificateOrderMapper.selectByUdidAndPurchaseType(appOrderVo.getUdid(),appOrderVo.getClassType(),loginUserId);

        if (!"1".equals(appOrderVo.getPoolType())){
            List<UserPoolConfigVo> config = userPoolConfigService.getConfig();
            UserPoolConfigVo userPoolConfigVo = config.stream().filter(t -> t.getVersionTypeCode().equals(appOrderVo.getVersionTypeCode())).findFirst().orElse(null);
            if (userPoolConfigVo==null){
                throw exception(USER_CERTIFICATE_ORDER_SITECONFIG);
            }
            appOrderVo.setTimeout(userPoolConfigVo.getTimeout());
            appOrderVo.setVersionTypeCode(userPoolConfigVo.getVersionTypeCode());
            appOrderVo.setVersionTypeName(userPoolConfigVo.getVersionTypeName());
        }
        //默认购买类型为新购
        appOrderVo.setBuyType("newPurchase");
        //是否扣钱
        boolean  priceFlag = true;

        Date date = new Date();
        //设定过期时间 ，如果是 质保，保存对应的过期时间
        int timeOutOrder = 0;
        //掉签查询 为掉签报异常  掉签更新状态
        if ( memberCertificateOrderDoByDb !=null  ){
            //存在下单记录
           // 判断是否掉签
            if (memberCertificateOrderDoByDb.getDropFlag()){
                //todo 掉签
                //获取是否过期
                Integer timeout = memberCertificateOrderDoByDb.getTimeout();
                LocalDateTime localDateTime = memberCertificateOrderDoByDb.getCreateTime();
                //获取系统默认时区
                ZoneId zoneId = ZoneId.systemDefault();
                //时区的日期和时间
                ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
                //获取时刻
                Date dateStart = Date.from(zonedDateTime.toInstant());
                long between = DateUtil.between( dateStart , date, DateUnit.DAY);
                if (between-timeout < 0){
                    //未超过售后时间 下单 但不扣钱
                    priceFlag = Boolean.FALSE;
                    appOrderVo.setBuyType("warranty");
                    timeOutOrder = timeout - (int)between;
                }
            }else {
                //未掉签的情况 抛出异常
                if (StrUtil.isEmpty(appOrderVo.getIsThird())){
                    if(!"1".equals(appOrderVo.getForce())){
                        throw exception(USER_CERTIFICATE_ORDER_UDID);
                    }
                }else {
                    //返回对应数据,先检测一下证书状态
                    cardSecurityService.certCheck(memberCertificateOrderDoByDb.getId());
                    return memberCertificateOrderMapper.selectById(memberCertificateOrderDoByDb.getId());
                }

            }
        }
        MobileProvisionCreateModel model = new MobileProvisionCreateModel();
//        MemberUserDO user = memberUserService.getUser(loginUserId);
        model.setUserName(user.getNickname());
        PriceVo priceVo = null;
        //独立池单独走逻辑
        if ("1".equals(appOrderVo.getPoolType())){
            //独立池
//            memberCertificateOrderMapper.insert(MemberCertificateOrderConvert.INSTANCE.convert(appOrderVo));
            //扣减证书 todo
            model.setUdid(appOrderVo.getUdid());
            model.setAccountType(AppleAccountType.INDEPENDENT_POOL);
            model.setAppAccountId(appOrderVo.getAppAccountId());
            model.setVersionType(appOrderVo.getVersionTypeCode());
            if ("0".equals(appOrderVo.getClassType())){
                model.setClassType(ClassType.SECOND);
            }else {
                model.setClassType(ClassType.APPOINTMENT);
            }
            if ("iphone".equals(appOrderVo.getDeviceType())){
                model.setDeviceType(AppleDeviceType.IPHONE);
            }else {
                model.setDeviceType(AppleDeviceType.PAD);
            }
            model.setUserId(loginUserId);
        }else {
            model.setUdid(appOrderVo.getUdid());
            model.setAccountType(AppleAccountType.PUBLIC_POOL);
            model.setAppAccountId(appOrderVo.getAppAccountId());
            model.setVersionType(appOrderVo.getVersionTypeCode());

            //todo
            if ("0".equals(appOrderVo.getClassType())){
                model.setClassType(ClassType.SECOND);
            }else {
                model.setClassType(ClassType.APPOINTMENT);
            }

            if ("iphone".equals(appOrderVo.getDeviceType())){
                model.setDeviceType(AppleDeviceType.IPHONE);
            }else {
                model.setDeviceType(AppleDeviceType.PAD);
            }
            model.setUserId(loginUserId);

            //判断购买类型是标准版VT3 iphone  秒出 只扣减设备数
            if("0".equals(appOrderVo.getClassType()) && appOrderVo.getVersionTypeCode().equals(STANDARD_EDITION_CODE) && "iphone".equals(appOrderVo.getDeviceType())){

                //不是售后的时候才扣钱
                if (!"warranty".equals(appOrderVo.getBuyType())){
                    int i = userExtendDO.getTotalDevice() - 1;
                    if (i<0){
                        //使用积分扣减 todo
                        priceVo =    pointReduce(appOrderVo, loginUserId, userExtendDO,priceFlag);
                    }else {
                        //不扣钱 且不统计利润 但扣设备数
                        priceFlag = Boolean.FALSE;
                        priceVo =    pointReduce(appOrderVo, loginUserId, userExtendDO,priceFlag);

//                        memberUserMapper.updateById(user);
                        //更新设备变动记录
                        log.info("udid扣减{}用户id{}时间{}",appOrderVo.getUdid(),user.getId(),DateUtil.now());
                        memberDeviceService.createDeviceRecord(loginUserId, 1, MemberPointBizTypeEnum.REDUCE_DEVICE, appOrderVo.getCertificateOrderCode(),i,userExtendDO.getTotalDevice(),priceVo.getTimeout(),appOrderVo.getVersionTypeName(),appOrderVo.getUdid());
                        log.info("购买设备扣减设备数量userId={}",userExtendDO.getUserId());
                        userExtendDO.setTotalDevice(userExtendDO.getTotalDevice() - 1);
                        memberUserExtendService.updateById(userExtendDO);
                    }
                }else {
                    priceFlag = Boolean.FALSE;
                    priceVo =    pointReduce(appOrderVo, loginUserId, userExtendDO,priceFlag);
                }

            }else {
                //积分扣减
                priceVo =  pointReduce(appOrderVo, loginUserId, userExtendDO,priceFlag);
            }
        }

        log.info("成本与利润信息{}{}时间{}",JSONUtil.toJsonStr(priceVo),appOrderVo.getUdid(),DateUtil.now());
        //插入利润 公共池
        if (!"1".equals(appOrderVo.getPoolType()) && priceFlag){
            if (priceVo ==null){
                throw exception(PRICE_EXISTS);
            }
            if ( priceVo.getPrice()==null ){
                throw exception(PRICE_EXISTS);
            }
            if (  priceVo.getCostPrice()==null){
                throw exception(PRICE_COST_EXISTS);
            }
            if (  priceVo.getTimeout()==null){
                throw exception(PRICE_COST_TIME_OUT_EXISTS);
            }
            ProfitSaveReqVO profitSaveReqVO = new ProfitSaveReqVO();
            profitSaveReqVO.setType(ADD_CERTIFICATE_ORDER.getType());
            profitSaveReqVO.setPrice(priceVo.getPrice());
            profitSaveReqVO.setCostPrice(priceVo.getCostPrice());
            profitSaveReqVO.setProfit(priceVo.getPrice().subtract(priceVo.getCostPrice()));
            profitSaveReqVO.setYear(DateUtil.year(date));
            profitSaveReqVO.setMonth(DateUtil.month(date));
            profitService.createProfit(profitSaveReqVO);
            log.info("成本与利润信息统计完毕{}时间{}",JSONUtil.toJsonStr(priceVo),DateUtil.now());
        }
        //判断是否是B系统调用A系统获取证书
        String token = orderNoRedisDAO.getValue(SITE_CONFIG_CACHE_TOKEN);
        String automaticFlag = orderNoRedisDAO.getValue(SITE_CONFIG_CACHE_AUTOMATIC_FLAG);
        String mainUrl = orderNoRedisDAO.getValue(SITE_CONFIG_CACHE_MAIN_URL);
        String mainCode = orderNoRedisDAO.getValue(SITE_CONFIG_CACHE_MAIN_CODE);
        if (ObjectUtil.isNotEmpty(token) && !"1".equals(appOrderVo.getPoolType())){
            //如果是优先调用
            if (automaticFlag.equals(Boolean.TRUE.toString())){
                if (StrUtil.isEmpty(mainUrl)){
                    throw exception(MAIN_URL_NOT);
                }
                SysLinkStrategy sysLinkStrategy = sysLinkStrategys.stream().filter(o ->StringUtils.equals(mainCode,o.getSysType())).findFirst().get();
                if (ObjectUtil.isEmpty(sysLinkStrategy)){
                    throw exception(LINK_FLAG_TRUE_UNREALIZED,mainCode);
                }
                MemberCertificateOrderDo ado ;
                try {
                    log.info("调用三方系统生成设备信息udid={}订单号={}时间={}",appOrderVo.getUdid(),appOrderVo.getCertificateOrderCode(),DateUtil.now());
                     ado = sysLinkStrategy.createOrder(appOrderVo);
                }catch (Exception e){
                    throw exception(MAIN_URL_EXCEPTION,e.getMessage());
                }
                ado.setSysId(ado.getId());
                ado.setId(null);
                ado.setUserId(loginUserId);
                ado.setSourceFlag(mainCode);
                ado.setUserName(user.getNickname());
                ado.setMainUrl(mainUrl);
                ado.setYear(DateUtil.year(date));
                ado.setMonth(DateUtil.month(date));
                String p12Url;
                String mpUrl;

                if (!sysLinkStrategy.getSysType().equals(SysFlagEnum.HUA_YANG.getType()) && !sysLinkStrategy.getSysType().equals(SysFlagEnum.HUA_YANG_V2.getType())){
                    //文件信息处理  p12Url mpUrl 从对应服务器上下载文件
                    if (StrUtil.isNotEmpty(ado.getP12Url())){
                        //todo 文件处理
                        try {
                            p12Url =  saveP12File(ado.getP12Url());
                            ado.setP12UrlFlag(true);
                            ado.setP12Url(p12Url);
                        }catch (Exception e){
                            //捕获不抛异常信息
                        }
                    }
                    if (StrUtil.isNotEmpty(ado.getMpUrl())){
                        //todo 文件处理
                        try {
                            mpUrl =  saveFile(ado.getMpUrl());
                            ado.setMpUrlFlag(true);
                            ado.setMpUrl(mpUrl);
                        }catch (Exception e){
                            //捕获不抛异常信息
                        }
                    }
                }

                //过期时间按本系统的时间来
                if (!"1".equals(appOrderVo.getPoolType())){
                    if (priceVo ==null){
                        throw exception(PRICE_EXISTS);
                    }
                    if (  priceVo.getTimeout()==null){
                        throw exception(PRICE_COST_TIME_OUT_EXISTS);
                    }
                    if (!"warranty".equals(appOrderVo.getBuyType())){
                        ado.setTimeout(priceVo.getTimeout());
                    }else {
                        //售后以前一个为主
                        ado.setTimeout(timeOutOrder);
                    }

                }else {
                    //个人池里没有过期时间一说
                    ado.setTimeout(0);
                }
                memberCertificateOrderMapper.insert(ado);
                // 检测证书
                cardSecurityService.certCheck(ado.getId());
                sendMessageToVx(date, model, user, ado,userExtendDO);
                return ado;
            }
        }

        MobileProvisionResultModel mobileProvision;
        try{
            log.info("调用证书生成接口参数{}",JSONUtil.toJsonStr(model));
            //证书接口 todo
             mobileProvision = appleDeviceService.createMobileProvision(model);
             if (mobileProvision==null){
                 throw exception(USER_CERTIFICATE_ORDER_NOT_RETURN);
             }
        }catch (Exception e){
            throw new IllegalArgumentException(e.getMessage());
        }

        //保存订单
        MemberCertificateOrderDo convert = MemberCertificateOrderConvert.INSTANCE.convert(appOrderVo);
        log.info("订单" + JSONUtil.toJsonStr(convert));
        log.info("生成的证书数据" + JSONUtil.toJsonStr(mobileProvision));
        convert.setMpUrl(mobileProvision.getProfileUrl());
        //todo
        convert.setP12Url(mobileProvision.getP12Url());
        convert.setP12Password(mobileProvision.getP12Password());
        convert.setAppAccountId(mobileProvision.getAppAccountId());
        convert.setUserId(loginUserId);
        convert.setCerId(mobileProvision.getCerId());
        convert.setCerName(mobileProvision.getCerName());
        convert.setCerNumber(mobileProvision.getCerNumber());
        convert.setDeviceId(mobileProvision.getDeviceId());
        convert.setDeviceModel(mobileProvision.getDeviceModel());
        convert.setAccountType(mobileProvision.getAccountType());
        convert.setUserName(user.getNickname());
        convert.setYear(DateUtil.year(date));
        convert.setMonth(DateUtil.month(date));
        if ("iphone".equals(appOrderVo.getDeviceType())){
            convert.setDeviceModel(AppleDeviceType.IPHONE.getDescription());
        }else {
            convert.setDeviceModel(AppleDeviceType.PAD.getDescription());
        }

        convert.setDropFlag(Boolean.FALSE);
        if (!"1".equals(appOrderVo.getPoolType())){
            if (priceVo ==null){
                throw exception(PRICE_EXISTS);
            }
            if (  priceVo.getTimeout()==null){
                throw exception(PRICE_COST_TIME_OUT_EXISTS);
            }
            convert.setSourceFlag(SysFlagEnum.CURSTATION.getType());
            convert.setTimeout(priceVo.getTimeout());
        }else {
            //个人池里没有过期时间一说
            convert.setTimeout(0);
            convert.setSourceFlag(SysFlagEnum.PRIVATE.getType());
        }
        memberCertificateOrderMapper.insert(convert);
        // 检测证书
        cardSecurityService.certCheck(convert.getId());
        sendMessageToVx(date, model, user, convert, userExtendDO);
        return convert;
    }

    private String saveFile(String p12Url) throws IOException {
            File tempFile = FileUtil.createTempFile(".mobileprovision", false);
            URL url = new URL(p12Url);
            URLConnection connection = url.openConnection();
            InputStream inputStream = connection.getInputStream();
            String fileName = UUID.fastUUID() + "." + FileUtil.getSuffix(tempFile);
            String file =  fileApi.createFile(fileName, "mb", IoUtil.readBytes(inputStream));
            System.out.println(file);
        return file;
    }

    private String saveP12File(String p12Url) throws IOException {
        File tempFile = FileUtil.createTempFile(".p12", false);
        URL url = new URL(p12Url);
        URLConnection connection = url.openConnection();
        InputStream inputStream = connection.getInputStream();
        String fileName = UUID.fastUUID() + "." + FileUtil.getSuffix(tempFile);
        String file =  fileApi.createFile(fileName, "p12", IoUtil.readBytes(inputStream));
        System.out.println(file);
        return file;
    }

    private static void sendMessageToVx(Date date, MobileProvisionCreateModel model, MemberUserDO user, MemberCertificateOrderDo convert, MemberUserExtendDO userExtendDO) {
        String className ;
        if ("0".equals(convert.getClassType())){
            className = "秒出";
        }else {
            className ="预约";
        }
        //发送短信 todo
        RobbleWXUtil.sendMessage("新出"+className+"证书<font color=\\\"warning\\\"> "+ date +"</font>,\n" +
                "         >编号:<font color=\\\"comment\\\"> "+ convert.getCerId() +  "</font>\n" +
                "         >用户:<font color=\\\"comment\\\"> "+ user.getNickname() +  "</font>\n" +
                "         >余额:<font color=\\\"comment\\\"> "+ userExtendDO.getTotalPoint() +  "</font>\n" +
                "         >版本:<font color=\\\"comment\\\"> "+ convert.getVersionTypeName() +  "</font>\n" +
                "         >平台:<font color=\\\"comment\\\"> "+ "本站" +  "</font>\n" +
                "         >名称:<font color=\\\"comment\\\"> "+ convert.getCerName() +  "</font>\n" +
                "         >设备:<font color=\\\"comment\\\"> "+ model.getDeviceType().getDescription() +  "</font>\n" +
                "         >udid:<font color=\\\"comment\\\"> "+ convert.getUdid() +  "</font>\n" +
                "         >操作:<font color=\\\"comment\\\">" + user.getNickname() +  "</font>"     );
    }

    @Override
    public PageResult<MemberCertificateOrderDo> getCertifiOrdeRecordPage(Long loginUserId, AppMemberCertificateOrderRecordPageReqVO pageReqVO) {
       return    memberCertificateOrderMapper.selectPage(loginUserId, pageReqVO);
    }

    /**
     * 证书上传
     *1获取设备
     * @param updateReqVO
     */
    @Override
    @Transactional
    public void updateOrderLink(UpdateReqVO updateReqVO) {
        MemberCertificateOrderDo memberCertificateOrderDo = memberCertificateOrderMapper.selectById(updateReqVO.getId());
        if (memberCertificateOrderDo==null){
//            throw new RuntimeException("未找到对应的设备信息");
            throw exception(USER_CERTIFICATE_ORDER_NOT_SELECT);

        }
        //修改对应的数据
        memberCertificateOrderDo.setP12Password(updateReqVO.getP12Password());
        memberCertificateOrderDo.setP12Url(updateReqVO.getP12Url());
        memberCertificateOrderDo.setMpUrl(updateReqVO.getProfileUrl());
        memberCertificateOrderMapper.updateById(memberCertificateOrderDo);
        //扣钱
        Long loginUserId = getLoginUserId();
//        MemberUserDO memberUserDO = memberUserMapper.selectById(loginUserId);
        MemberUserExtendDO memberUserExtendDO = memberUserExtendMapper.selectByUserId(loginUserId);
        //获取对应的上传证书的价格
        SiteConfigurationVo config = siteConfigurationService.getConfig();
        boolean flag  = memberUserExtendDO.getTotalPoint().compareTo(config.getUpPrice()) < 0;
        if (flag){
//            throw new RuntimeException("余额不足");
            throw exception(USER_POINT_NOT_ENOUGH);
        }
        memberUserExtendDO.setTotalPoint(memberUserExtendDO.getTotalPoint().subtract(config.getUpPrice()));
        //跟新消费总金额
        memberUserExtendDO.setSpendingPower(memberUserExtendDO.getSpendingPower().add(config.getUpPrice()));
        log.info("设备上传扣减积分userId={}",memberUserExtendDO.getUserId());
        memberUserExtendService.updateById(memberUserExtendDO);

//        memberUserMapper.updateById(memberUserDO);
        pointRecordService.createPointRecord(loginUserId,config.getUpPrice(), MemberPointBizTypeEnum.REDUCE_RECHARGE_ORDER, memberCertificateOrderDo.getCertificateOrderCode(),memberUserExtendDO.getTotalPoint().subtract(config.getUpPrice()),memberUserExtendDO.getTotalPoint(),null,null,null);
        //插入操作成本
        ProfitSaveReqVO profitSaveReqVO = new ProfitSaveReqVO();
        profitSaveReqVO.setType(ADD_UP_LOAD.getType());
        profitSaveReqVO.setPrice(config.getUpPrice());
        profitSaveReqVO.setCostPrice(config.getUpCost());
        profitSaveReqVO.setProfit(config.getUpPrice().subtract(config.getUpCost()));
        Date date = new Date();
        profitSaveReqVO.setYear(DateUtil.year(date));
        profitSaveReqVO.setMonth(DateUtil.month(date));
        profitService.createProfit(profitSaveReqVO);
        fileApi.moveFile(CharSequenceUtil.subAfter( updateReqVO.getP12Url(), "/get/", false),"p12");
        fileApi.moveFile(CharSequenceUtil.subAfter( updateReqVO.getProfileUrl(), "/get/", false),"mb");

    }

    /**
     * 修改备注
     *
     * @param updateRemarkReqVO
     */
    @Override
    @Transactional
    public void updateOrderRemark(UpdateRemarkReqVO updateRemarkReqVO) {
        MemberCertificateOrderDo memberCertificateOrderDo = memberCertificateOrderMapper.selectById(updateRemarkReqVO.getId());
        if (memberCertificateOrderDo==null){
//            throw new RuntimeException("未找到对应的设备信息");
            throw exception(USER_CERTIFICATE_ORDER_NOT_SELECT);
        }
        memberCertificateOrderDo.setRemark(updateRemarkReqVO.getRemark());
        memberCertificateOrderMapper.updateById(memberCertificateOrderDo);
    }

    @Override
    public void deleteById(Long id) {
        memberCertificateOrderMapper.deleteById(id);
    }

    @Override
    public BigDecimal queryPrice(AppMemberCertificateOrderVo appOrderVo) {
        BigDecimal price ;
        Long loginUserId = getLoginUserId();
        //积分扣减
        //询价 优先查看是否存在私有价格
        List<MemberUserPriceDetailDo> memberUserPriceDetailDos = memberUserPriceDetailService.getUserByUserId(loginUserId);
        MemberUserPriceDetailDo memberUserPriceDetailDo = memberUserPriceDetailDos.stream().filter(t -> t.getDeviceType().equals(appOrderVo.getDeviceType()) && t.getPurchaseType().equals(appOrderVo.getClassType()) && t.getVersionTypeCode().equals(appOrderVo.getVersionTypeCode())).findFirst().orElse(null);
        //如果不存在，获取前端站点配置里面的价格
        if (memberUserPriceDetailDo==null || memberUserPriceDetailDo.getPrice().compareTo(BigDecimal.ZERO) <= 0 ){
            List<UserPoolConfigDetailVo> allConfig = userPoolConfigDetailService.getAllConfig();
            UserPoolConfigDetailVo userPoolConfigDetailVo = allConfig.stream().filter(t -> t.getDeviceType().equals(appOrderVo.getDeviceType()) && t.getPurchaseType().equals(appOrderVo.getClassType()) && t.getVersionTypeCode().equals(appOrderVo.getVersionTypeCode())).findFirst().orElse(null);
            if (userPoolConfigDetailVo == null){
                log.info("未找到价格配置");
//                throw ex("未找到价格配置");
//                throw exception(USER_CERTIFICATE_ORDER_NOT_SELECT);
                return BigDecimal.ZERO;
            }
            price = userPoolConfigDetailVo.getPrice();
        }else {
            price = memberUserPriceDetailDo.getPrice();
        }
        return price;
    }

    @Override
    public CertificateOrderCountVo queryCount() {
        CertificateOrderCountVo vo = new CertificateOrderCountVo();

         Date date = new Date();
        DateUtil.beginOfDay(date);
        // 今天的订单数
        List<OrderUserCountsByTime> orderUserCountsByTimeTodays = memberCertificateOrderMapper.selectCountBetween(DateUtil.beginOfDay(date), DateUtil.endOfDay(date));
        // 昨天的订单数
        List<OrderUserCountsByTime> orderUserCountsByTimeDay= memberCertificateOrderMapper.selectCountBetween(DateUtil.beginOfDay(DateUtil.offsetDay(date ,-1)),DateUtil.endOfDay(DateUtil.offsetDay(date ,-1)));
        // 前三天的订单数
        List<OrderUserCountsByTime> orderUserCountsByTimeThrees= memberCertificateOrderMapper.selectCountBetween(DateUtil.beginOfDay( DateUtil.offsetDay(date ,-3)),DateUtil.endOfDay(DateUtil.offsetDay(date ,-1)));
        // 本月的订单数
        List<OrderUserCountsByTime> orderUserCountsByTimeMonths = memberCertificateOrderMapper.selectCountBetween(DateUtil.beginOfMonth(date),DateUtil.endOfMonth(date));
        // 上个月的订单数
        List<OrderUserCountsByTime> orderUserCountsByTimeLastMonths = memberCertificateOrderMapper.selectCountBetween(DateUtil.beginOfMonth(DateUtil.offsetMonth(date ,-1)), DateUtil.endOfMonth(DateUtil.offsetMonth(date, -1)));

        // 今年的订单数
        List<OrderUserCountsByTime> orderUserCountsByTimeYears = memberCertificateOrderMapper.selectCountBetween(DateUtil.beginOfYear(date),DateUtil.endOfYear(date));


        orderUserCountsByTimeTodays.forEach(t->{
            if ("1".equals(t.getClassType())){
                vo.setAddToday(t.getCountnumber());
            }else {
                vo.setAddToday1(t.getCountnumber());
            }
        });
        orderUserCountsByTimeDay.forEach(t->{
            if ("1".equals(t.getClassType())){
                vo.setYesterday(t.getCountnumber());
            }else {
                vo.setYesterday1(t.getCountnumber());
            }
        });
        orderUserCountsByTimeThrees.forEach(t->{
            if ("1".equals(t.getClassType())){
                vo.setAddThree(t.getCountnumber());
            }else {
                vo.setAddThree1(t.getCountnumber());
            }
        });
        orderUserCountsByTimeMonths.forEach(t->{
            if ("1".equals(t.getClassType())){
                vo.setAddMonth(t.getCountnumber());
            }else {
                vo.setAddMonth1(t.getCountnumber());
            }
        });
        orderUserCountsByTimeLastMonths.forEach(t->{
            if ("1".equals(t.getClassType())){
                vo.setAddLastMonth(t.getCountnumber());
            }else {
                vo.setAddLastMonth1(t.getCountnumber());
            }
        });
        orderUserCountsByTimeYears.forEach(t->{
            if ("1".equals(t.getClassType())){
                vo.setAddYear(t.getCountnumber());
            }else {
                vo.setAddYear1(t.getCountnumber());
            }
        });

        return vo;
    }

    /**
     * 一月 Jan. January
     *
     * 二月 Feb. February
     *
     * 三月 Mar. March
     *
     * 四月 Apr. April
     *
     * 五月 May. May
     *
     * 六月 Jun. June
     *
     * 七月 Jul. July
     *
     * 八月 Aug. August
     *
     * 九月 Sept. September
     *
     * 十月 Oct. October
     *
     * 十一月 Nov. November
     *
     * 十二月 Dec. December
     * @return
     */
    @Override
    public CertificateOrderCountTypeVo queryCountByType() {
        Date date = new Date();
        CertificateOrderCountTypeVo vo = new CertificateOrderCountTypeVo();
        List<Long> countOut=new ArrayList<>();
        List<Long> reservationCount=new ArrayList<>();
        Long JanLong1 = memberCertificateOrderMapper.selectCountByYearAndMonth(DateUtil.year(date), 1, "1");
        Long FebLong1 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,2,"1");
        Long MarLong1 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,3,"1");
        Long AprLong1 =memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,4,"1");
        Long MayLong1 =memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,5,"1");
        Long JunLong1 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,6,"1");
        Long JulLong1 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,7,"1");
        Long AugLong1 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,8,"1");
        Long SeptLong1 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,9,"1");
        Long OctLong1 =  memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,10,"1");
        Long NovLong1 =memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,11,"1");
        Long DecLong1 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,12,"1");
        countOut.add(JanLong1);
        countOut.add(FebLong1);
        countOut.add(MarLong1);
        countOut.add(AprLong1);
        countOut.add(MayLong1);
        countOut.add(JunLong1);
        countOut.add(JulLong1);
        countOut.add(AugLong1);
        countOut.add(SeptLong1);
        countOut.add(OctLong1);
        countOut.add(NovLong1);
        countOut.add(DecLong1);
        Long JanLong2 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,1,"0");
        Long FebLong2 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,2,"0");
        Long MarLong2 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,3,"0");
        Long AprLong2 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,4,"0");
        Long MayLong2 =memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,5,"0");
        Long JunLong2 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,6,"0");
        Long JulLong2 =memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,7,"0");
        Long AugLong2 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,8,"0");
        Long SeptLong2 =memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,9,"0");
        Long OctLong2 =memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,10,"0");
        Long NovLong2 =memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,11,"0");
        Long DecLong2 = memberCertificateOrderMapper.selectCountByYearAndMonth( DateUtil.year(date) ,12,"0");
        reservationCount.add(JanLong2);
        reservationCount.add(FebLong2);
        reservationCount.add(MarLong2);
        reservationCount.add(AprLong2);
        reservationCount.add(MayLong2);
        reservationCount.add(JunLong2);
        reservationCount.add(JulLong2);
        reservationCount.add(AugLong2);
        reservationCount.add(SeptLong2);
        reservationCount.add(OctLong2);
        reservationCount.add(NovLong2);
        reservationCount.add(DecLong2);
        vo.setCountOut(countOut);
        vo.setReservationCount(reservationCount);
        return vo;
    }

    /**
     * 证书排行
     *
     * @return
     */
    @Override
    public CertificateOrderCountUserVo CertificateOrderCountUserVo(String flag) {
        CertificateOrderCountUserVo vo = new CertificateOrderCountUserVo();
        List<String> userNames=new ArrayList<>();
        List<Long> reservationCounts=new ArrayList<>();
        List<Long> outInCounts=new ArrayList<>();
        String startTime = null,endTime = null;
        if(StringUtils.isNotBlank(flag) && "yesterday".equals(flag)){
            startTime = DateUtil.format(DateUtil.yesterday(), DatePattern.NORM_DATE_PATTERN) + " 00:00:00";
            endTime = DateUtil.format(DateUtil.yesterday(), DatePattern.NORM_DATE_PATTERN)+ " 23:59:59";
        }else if("today".equals(flag)){
            startTime = DateUtil.today() + " 00:00:00";
            endTime = DateUtil.today() + " 23:59:59";
        }

        //获取下单最多的15个人的id
         List<Long>  userIds =  memberCertificateOrderMapper.selectCountByUser(startTime,endTime);
        if(CollectionUtil.isEmpty(userIds)){
            return vo;
        }
        //获取用户名称
        List<MemberUserDO> memberUserDOS = memberUserMapper.selectBatchIds(userIds);
        Map<Long, String> nickNameMap = memberUserDOS.stream().collect(Collectors.toMap(MemberUserDO::getId, MemberUserDO::getNickname));
        //按名字统计
        List<OrderUserCounts> reservationList = memberCertificateOrderMapper.selectCountByUserId(userIds, 0,startTime,endTime);
        Map<Long, Long> reservationMap = reservationList.stream().collect(Collectors.toMap(OrderUserCounts::getUserId, OrderUserCounts::getCountnumber));
        List<OrderUserCounts> outInCountList = memberCertificateOrderMapper.selectCountByUserId(userIds, 1,startTime,endTime);
        Map<Long, Long> outInCountMap = outInCountList.stream().collect(Collectors.toMap(OrderUserCounts::getUserId, OrderUserCounts::getCountnumber));
        nickNameMap.forEach((k, v)->{
            userNames.add(v);
            reservationCounts.add(reservationMap.getOrDefault(k, 0L));
            outInCounts.add(outInCountMap.getOrDefault(k, 0L));

        });
        vo.setUserNames(userNames);
        vo.setOutInCounts(outInCounts);
        vo.setReservationCounts(reservationCounts);
        return vo;
    }




    @Override
    public void downloadCertificate(HttpServletRequest request, HttpServletResponse response) throws Exception{

        String id = request.getParameter("id");
        Assert.isTrue(StringUtils.isNotBlank(id),"证书id不能为空");
        MemberCertificateOrderDo memberCertificateOrderDo = memberCertificateOrderMapper.selectById(id);

        Assert.isTrue(null!=memberCertificateOrderDo ,"未找到对应的证书信息");
        Assert.isTrue(Boolean.FALSE.equals(memberCertificateOrderDo.getDropFlag()),"证书已掉签");

        if(StringUtils.equals( memberCertificateOrderDo.getClassType(),"1") && StringUtils.isBlank(memberCertificateOrderDo.getMpUrl()) && StrUtil.isEmpty(memberCertificateOrderDo.getMainUrl())){
            //重新获取描述文件
            memberCertificateOrderDo.setMpUrl(appleDeviceService.reGetMobileProvision(memberCertificateOrderDo.getId()));
        }

        Assert.isTrue(StringUtils.isNotBlank(memberCertificateOrderDo.getP12Url())
        && StringUtils.isNotBlank(memberCertificateOrderDo.getMpUrl() ),"证书生成中");

        //p12文件url
        String p12Url = memberCertificateOrderDo.getP12Url();
        String p12Path = CharSequenceUtil.subAfter(p12Url, "/get/", false);
        String p12Config = p12Url.substring(p12Url.indexOf("/file/") + "/file/".length(), p12Url.indexOf("/get/"));
        String p12FilePath = fileApi.getFilePath(Long.valueOf(p12Config), p12Path);

        //描述文件url
        String mpUrl = memberCertificateOrderDo.getMpUrl();
        String appPath = CharSequenceUtil.subAfter(mpUrl, "/get/", false);
        String mpConfig = mpUrl.substring(mpUrl.indexOf("/file/") + "/file/".length(), mpUrl.indexOf("/get/"));
        String mpFilePath = fileApi.getFilePath(Long.valueOf(mpConfig), appPath);

        // 计算总大小（p12 + mp）
        long p12Size = new File(p12FilePath).length();
        long mpSize = new File(mpFilePath).length();
//        long totalSize = p12Size + mpSize;

        // 将p12和url压缩成zip 下载zip
        // 设置响应头
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment;filename="+memberCertificateOrderDo.getUdid()+".zip");
//        response.setHeader("Content-Length", String.valueOf(totalSize)); // ✅ 关键：设置文件大小
//        response.setHeader("Accept-Ranges", "bytes"); // ✅ 支持断点续传（可选）

        try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
            // 添加p12文件到压缩包
            try (FileInputStream p12Fis = new FileInputStream(p12FilePath)) {
                ZipEntry p12Entry = new ZipEntry("certificate_password_"+1+".p12");
                zos.putNextEntry(p12Entry);
                byte[] buffer = new byte[1024];
                int len;
                while ((len = p12Fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }
                zos.closeEntry();
            }

            // 添加描述文件到压缩包
            try (FileInputStream mpFis = new FileInputStream(mpFilePath)) {
                ZipEntry mpEntry = new ZipEntry("profile.mobileprovision");
                zos.putNextEntry(mpEntry);
                byte[] buffer = new byte[1024];
                int len;
                while ((len = mpFis.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }
                zos.closeEntry();
            }

            zos.flush();
        } catch (IOException e) {
            throw new RuntimeException("证书文件打包失败", e);
        }

    }

    @Override
    public void downloadCertificateCheck(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String id = request.getParameter("id");
        Assert.isTrue(StringUtils.isNotBlank(id),"证书id不能为空");
        MemberCertificateOrderDo memberCertificateOrderDo = memberCertificateOrderMapper.selectById(id);

        Assert.isTrue(null!=memberCertificateOrderDo ,"未找到对应的证书信息");
        Assert.isTrue(Boolean.FALSE.equals(memberCertificateOrderDo.getDropFlag()),"证书已掉签");

        if(StringUtils.equals( memberCertificateOrderDo.getClassType(),"1") && StringUtils.isBlank(memberCertificateOrderDo.getMpUrl())){
            //重新获取描述文件
            if(ObjectUtil.isNotEmpty(memberCertificateOrderDo.getMainUrl()) && !memberCertificateOrderDo.getMpUrlFlag()){
                //描述文件未处理
                SysLinkStrategy sysLinkStrategy = sysLinkStrategys.stream().filter(o ->StringUtils.equals(memberCertificateOrderDo.getSourceFlag(),o.getSysType())).findFirst().get();
                AppMemberCertificateOrderVo byId = sysLinkStrategy.getById(memberCertificateOrderDo);
                if (!sysLinkStrategy.getSysType().equals(SysFlagEnum.HUA_YANG.getType()) && !sysLinkStrategy.getSysType().equals(SysFlagEnum.HUA_YANG_V2.getType())){
                    try {
                        String mpUrl =  saveFile(byId.getMpUrl());
                        memberCertificateOrderDo.setMpUrlFlag(true);
                        memberCertificateOrderDo.setMpUrl(mpUrl);
                    }catch (Exception e){
                        throw exception(MAIN_URL_EXCEPTION,e.getMessage());
                    }
                }else {
                    log.info("华阳不需要再次保存数据");
                    memberCertificateOrderDo.setMpUrlFlag(true);
                    memberCertificateOrderDo.setMpUrl(byId.getMpUrl());
                }

            }else {
                log.info("本站重新获取描述文件");
                memberCertificateOrderDo.setMpUrl(appleDeviceService.reGetMobileProvision(memberCertificateOrderDo.getId()));
            }

        }
        memberCertificateOrderMapper.updateById(memberCertificateOrderDo);
        log.info("当前设备信息{}",JSONUtil.toJsonStr(memberCertificateOrderDo));
        Assert.isTrue(StringUtils.isNotBlank(memberCertificateOrderDo.getP12Url())
                && StringUtils.isNotBlank(memberCertificateOrderDo.getMpUrl() ),"证书生成中");
    }



    @Override
    public MemberCertificateOrderDo getByUdidAndUserId(String udid,Long userId) {
        return memberCertificateOrderMapper.selectByUdidAndUserId(udid,userId);
    }

    @Override
    public List<MemberCertificateOrderDo> getListByUserAndUdid(Long userId, String udid) {
        return memberCertificateOrderMapper.getListByUserAndUdid(userId,udid);
    }

    /**
     * 用户自己上传设备信息
     * @param updateReqVO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void loadDevice( UpdateReqVO updateReqVO) throws Exception {
        //调用工具类获取信息 todo

        Long loginUserId =  getLoginUserId();
        MemberUserDO memberUserDO = memberUserMapper.selectById(loginUserId);
        MemberUserExtendDO memberUserExtendDO = memberUserExtendMapper.selectByUserId(loginUserId);
//        if(memberUserDO.getUpFlag().equals(CommonStatusEnum.DISABLE.getStatus())){
//            throw exception(UP_LOAD_ERROR,memberUserDO.getNickname());
//        }
        //校验P12密码是否正确 如果不报错就证明数据正确
        String p12Str=null;
        try {
            String p12Path = CharSequenceUtil.subAfter(updateReqVO.getP12Url(), "/get/", false);
            String p12Config = updateReqVO.getP12Url().substring(updateReqVO.getP12Url().indexOf("/file/") + "/file/".length(), updateReqVO.getP12Url().indexOf("/get/"));
            String p12FilePath = fileApi.getFilePath(Long.valueOf(p12Config), p12Path);
            p12Str = Base64Encoder.encode(FileUtil.readBytes(p12FilePath));
            CertStatusDTO certStatusDTO = OCSPUtil.checkCertStatus(p12Str, updateReqVO.getP12Password(), 1);
            CertUtil.getCertInfo(p12Str, updateReqVO.getP12Password(), certStatusDTO);
            log.info("设备{}证书掉签检查结果为:{}", updateReqVO.getId(), JSON.toJSONString(certStatusDTO));
        }catch (Exception e){
            throw exception(DROP_SIGNATURE_ERROR,e.getMessage());
        }


        String path = CharSequenceUtil.subAfter(updateReqVO.getProfileUrl(), "/get/", false);
        String configFile = updateReqVO.getProfileUrl().substring(updateReqVO.getProfileUrl().indexOf("/file/") + "/file/".length(), updateReqVO.getProfileUrl().indexOf("/get/"));
        String filePath = fileApi.getFilePath(Long.valueOf(configFile), path);
//        appOrderVo.setCertificateOrderCode(orderNoRedisDAO.generate(CERTIFICATE_ORDER));
        String generate = orderNoRedisDAO.generate(CERTIFICATE_ORDER);
        Map<String, Object> map = MbUtil.parseProvisionFile(filePath);
        MemberCertificateOrderDo saveDo =  new MemberCertificateOrderDo();
        saveDo.setUserId(loginUserId);
        saveDo.setSourceFlag("userUpload");
        saveDo.setUdid(map.get("udid").toString());
        saveDo.setMpUrl(updateReqVO.getProfileUrl());
        saveDo.setP12Url(updateReqVO.getP12Url());
        saveDo.setCertificateOrderCode(generate);
        saveDo.setP12Password(updateReqVO.getP12Password());
        saveDo.setCerName(map.get("teamName").toString());
        saveDo.setPoolType("2");
        saveDo.setAccountType("1");
        saveDo.setUserName(memberUserDO.getNickname());

        String mpStr = new String(FileUtil.readBytes(filePath), "UTF-8");
        CertAndMobileprovisionDTO certAndMobileprovisionDTO = CertUtil.checkMobileProvesion(p12Str, mpStr, updateReqVO.getP12Password());
        Assert.isTrue(Boolean.TRUE.equals(certAndMobileprovisionDTO.getMatchFlag()) , "p12和描述文件不匹配!");
        memberCertificateOrderMapper.insert(saveDo);
        cardSecurityService.certCheck(saveDo.getId());

        //扣钱
//        Long loginUserId = getLoginUserId();

        //获取对应的上传证书的价格
        SiteConfigurationVo config = siteConfigurationService.getConfig();
        boolean flag  = memberUserExtendDO.getTotalPoint().compareTo(config.getUpPrice()) < 0;
        if (flag){
//            throw new RuntimeException("余额不足");
            throw exception(USER_POINT_NOT_ENOUGH);
        }
        memberUserExtendDO.setTotalPoint(memberUserExtendDO.getTotalPoint().subtract(config.getUpPrice()));
        //跟新消费总金额
        memberUserExtendDO.setSpendingPower(memberUserExtendDO.getSpendingPower().add(config.getUpPrice()));
        log.info("设备上传扣减积分userId={}",memberUserExtendDO.getUserId());
        memberUserExtendService.updateById(memberUserExtendDO);
        pointRecordService.createPointRecord(loginUserId,config.getUpPrice(), MemberPointBizTypeEnum.REDUCE_RECHARGE_ORDER, saveDo.getCertificateOrderCode(),memberUserExtendDO.getTotalPoint().subtract(config.getUpPrice()),memberUserExtendDO.getTotalPoint(),null,null,null);
        //插入操作成本
        ProfitSaveReqVO profitSaveReqVO = new ProfitSaveReqVO();
        profitSaveReqVO.setType(ADD_UP_LOAD.getType());
        profitSaveReqVO.setPrice(config.getUpPrice());
        profitSaveReqVO.setCostPrice(config.getUpCost());
        profitSaveReqVO.setProfit(config.getUpPrice().subtract(config.getUpCost()));
        Date date = new Date();
        profitSaveReqVO.setYear(DateUtil.year(date));
        profitSaveReqVO.setMonth(DateUtil.month(date));
        profitService.createProfit(profitSaveReqVO);
        fileApi.moveFile(CharSequenceUtil.subAfter( updateReqVO.getP12Url(), "/get/", false),"p12");
        fileApi.moveFile(CharSequenceUtil.subAfter( updateReqVO.getProfileUrl(), "/get/", false),"mb");
    }

    @Override
    public MemberCertificateOrderDo getById(Long id) {
        return memberCertificateOrderMapper.selectById(id);
    }

    @Override
    public void updateById(MemberCertificateOrderDo memberCertificateOrderDo) {
        memberCertificateOrderMapper.updateById(memberCertificateOrderDo);
    }

    /**
     * 其他系统文件转换处理 默认半个小时跑1000条数据
     */
    @Override
    @Transactional
    public void excuteSignTask() {
        //查询
     List<MemberCertificateOrderDo>   list =  memberCertificateOrderMapper.selectOtherSysFileList();
     if (!CollectionUtil.isEmpty(list)){
         list.stream().forEach(t->{
             SysLinkStrategy sysLinkStrategy = sysLinkStrategys.stream().filter(o ->StringUtils.equals(t.getSourceFlag(),o.getSysType())).findFirst().get();
             if (ObjectUtil.isEmpty(sysLinkStrategy)){
                return;
             }
             if (StrUtil.isNotEmpty(t.getP12Url()) && !t.getP12UrlFlag()){
                 //todo 文件处理
                 try {
                    String  p12Url =  saveP12File(t.getP12Url());
                     t.setP12UrlFlag(true);
                     t.setP12Url(p12Url);
                 }catch (Exception e){
                     //捕获不抛异常信息
                 }
             }else {
                 //文件为空时需要去其他系统重新拉去
                 AppMemberCertificateOrderVo byId = sysLinkStrategy.getById(t);
                 if (!ObjectUtil.isEmpty(byId) && StrUtil.isNotEmpty(byId.getP12Url())){
                     try {
                         String  p12Url =  saveP12File(byId.getP12Url());
                         t.setP12UrlFlag(true);
                         t.setP12Url(p12Url);
                     }catch (Exception e){
                         //捕获不抛异常信息
                     }
                 }

             }
             if (StrUtil.isNotEmpty(t.getMpUrl()) && !t.getMpUrlFlag()){
                 //todo 文件处理
                 try {
                     String mpUrl =  saveFile(t.getMpUrl());
                     t.setMpUrlFlag(true);
                     t.setMpUrl(mpUrl);
                 }catch (Exception e){
                     //捕获不抛异常信息
                 }
             }else {
                 AppMemberCertificateOrderVo byId = sysLinkStrategy.getById(t);
                 if (!ObjectUtil.isEmpty(byId) && StrUtil.isNotEmpty(byId.getMpUrl())){
                     try {
                         String  mpUrl =  saveFile(byId.getMpUrl());
                         t.setMpUrlFlag(true);
                         t.setMpUrl(mpUrl);
                     }catch (Exception e){
                         //捕获不抛异常信息
                     }
                 }
             }
         });
     }
        memberCertificateOrderMapper.insertOrUpdateBatch(list);
    }

    @Override
    public BigDecimal queryMyPrice(AppMemberCertificateOrderVo appOrderVo) {
        BigDecimal price ;
        Long loginUserId = getLoginUserId();
        //积分扣减
        //询价 优先查看是否存在私有价格
        List<MemberUserPriceDetailDo> memberUserPriceDetailDos = memberUserPriceDetailService.getUserByUserId(loginUserId);
        MemberUserPriceDetailDo memberUserPriceDetailDo = memberUserPriceDetailDos.stream().filter(t -> t.getDeviceType().equals(appOrderVo.getDeviceType()) && t.getPurchaseType().equals(appOrderVo.getClassType()) && t.getVersionTypeCode().equals(appOrderVo.getVersionTypeCode())).findFirst().orElse(null);
        if (memberUserPriceDetailDo==null || memberUserPriceDetailDo.getPrice().compareTo(BigDecimal.ZERO) <= 0 ){
            return BigDecimal.ZERO;
        }
        return memberUserPriceDetailDo.getPrice();
    }

    /**
     * B系统掉A系统的接口
     *
     * @param appOrderVo
     * @return
     */
//    @Override
//    @Transactional
//    public MemberCertificateOrderDo createOrderByOther(AppMemberCertificateOrderVo appOrderVo) {
//        //根据 token 获取用户信息
//        MemberUserDO userByUserToken = memberUserService.getUserByUserToken(appOrderVo.getSysToken());
//        if (ObjectUtil.isNotEmpty(userByUserToken)){
//            throw exception(USER_NOT_EXISTS);
//        }
//        if(userByUserToken.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())){
//            throw exception(USER_DISABLED);
//        }
//        appOrderVo.setUserId(userByUserToken.getId());
//        return  this.createOrder(appOrderVo);
//    }

    public PriceVo pointReduce(AppMemberCertificateOrderVo appOrderVo, Long userId, MemberUserExtendDO user ,Boolean priceFlag) {
        PriceVo pay = new PriceVo();
        BigDecimal price ;
        //积分扣减
        //询价 优先查看是否存在私有价格
        List<MemberUserPriceDetailDo> memberUserPriceDetailDos = memberUserPriceDetailService.getUserByUserId(userId);
        MemberUserPriceDetailDo memberUserPriceDetailDo = memberUserPriceDetailDos.stream().filter(t -> t.getDeviceType().equals(appOrderVo.getDeviceType()) && t.getPurchaseType().equals(appOrderVo.getClassType()) && t.getVersionTypeCode().equals(appOrderVo.getVersionTypeCode())).findFirst().orElse(null);
        //如果不存在，获取前端站点配置里面的价格
        if (memberUserPriceDetailDo==null || memberUserPriceDetailDo.getPrice().compareTo(BigDecimal.ZERO) <= 0 ){
            List<UserPoolConfigDetailVo> allConfig = userPoolConfigDetailService.getAllConfig();
            UserPoolConfigDetailVo userPoolConfigDetailVo = allConfig.stream().filter(t -> t.getDeviceType().equals(appOrderVo.getDeviceType()) && t.getPurchaseType().equals(appOrderVo.getClassType()) && t.getVersionTypeCode().equals(appOrderVo.getVersionTypeCode())).findFirst().orElse(null);
            if (userPoolConfigDetailVo == null){
//                throw new RuntimeException("未找到价格配置");
                throw exception(USER_CERTIFICATE_ORDER_PRICE);
            }
            price = userPoolConfigDetailVo.getPrice();
            pay.setCostPrice(userPoolConfigDetailVo.getCostPrice());
            pay.setPrice(price);
            pay.setTimeout(userPoolConfigDetailVo.getTimeout());
        }else {
            price = memberUserPriceDetailDo.getPrice();
            pay.setCostPrice(memberUserPriceDetailDo.getCostPrice());
            pay.setPrice(price);
            pay.setTimeout(memberUserPriceDetailDo.getTimeout());
        }
        if(priceFlag){
            //扣减积分
            BigDecimal subtract = user.getTotalPoint().subtract(price);
            if (subtract.compareTo(BigDecimal.ZERO)<0){
                throw exception(USER_POINT_NOT_ENOUGH);
            }
            log.info("udid扣减{}用户id{}时间{}",appOrderVo.getUdid(),userId,DateUtil.now());
            pointRecordService.createPointRecord(userId,price, MemberPointBizTypeEnum.REDUCE_RECHARGE, appOrderVo.getCertificateOrderCode(),subtract,user.getTotalPoint(),appOrderVo.getTimeout(),appOrderVo.getVersionTypeName(),appOrderVo.getUdid());
            user.setTotalPoint(subtract);
            log.info("购买设备扣减积分userId={}",user.getUserId());
            memberUserExtendService.updateById(user);
            log.info("udid扣减{}用户id{}时间{}扣减完成",appOrderVo.getUdid(),userId,DateUtil.now());
        }
        return pay;
    }
}
